package ru.ifmo.tanya.core.calls;

import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import ru.ifmo.tanya.core.huntgroups.HuntGroup;
import ru.ifmo.tanya.core.users.User;
import ru.ifmo.tanya.core.users.UserManager;
import ru.ifmo.tanya.db.DataBaseManager;
import ru.ifmo.tanya.db.HuntGroupManager;

import java.sql.*;
import java.util.Date;
import java.util.List;


public class CallManager {

    private final HuntGroupManager huntGroupManager = new HuntGroupManager();
    private final UserManager userManager = new UserManager();

    private final ParameterizedRowMapper<Call> mapper = new ParameterizedRowMapper<Call>() {
        @Override
        public Call mapRow(ResultSet resultSet, int i) throws SQLException {
            return new Call(
                    resultSet.getInt("id"),
                    resultSet.getString("caller"),
                    huntGroupManager.getHuntGroupById(resultSet.getInt("hunt_group_id")),
                    resultSet.getTimestamp("creation_time"),
                    userManager.getUserById(resultSet.getInt("answerer_id")),
                    resultSet.getString("who_finished"),
                    resultSet.getTimestamp("answer_time"),
                    resultSet.getTimestamp("completed_time")
            );
        }
    };

    public int addCall(final String caller, final Date creationTime, final HuntGroup huntGroup) {
        PreparedStatementCreator statementCreator = new PreparedStatementCreator() {
            @Override
            public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
                PreparedStatement statement = connection.prepareStatement("INSERT INTO calls (hunt_group_id, caller, creation_time) VALUES (?, ?, ?)");
                statement.setInt(1, huntGroup.getId());
                statement.setString(2, caller);
                statement.setTimestamp(3, new Timestamp(creationTime.getTime()));
                return statement;
            }
        };
        GeneratedKeyHolder keyHolder = new GeneratedKeyHolder();
        DataBaseManager.getJdbcTemplate().update(statementCreator, keyHolder);
        return keyHolder.getKey().intValue();
    }

    public User getCallAnswerer(int callId) {
        List<Call> calls = DataBaseManager.getJdbcTemplate().query("SELECT * FROM calls WHERE id = ?", mapper, callId);
        if (calls.isEmpty()) {
            return null;
        }
        Call call = calls.get(0);
        if (call.getAnswerer() != null) {
            return call.getAnswerer();
        }
        return null;
    }

    public void callAnswered(Call call, User answerer) {
        DataBaseManager.getJdbcTemplate().update("UPDATE calls SET answer_time = CURRENT_TIMESTAMP(), answerer_id = ? WHERE id = ?", answerer.getId(), call.getId());
    }

    public void callEnded(int callId, String whoFinished) {
        DataBaseManager.getJdbcTemplate()
                .update("UPDATE calls SET completed_time = CURRENT_TIMESTAMP(), who_finished = ? WHERE id = ?", whoFinished, callId);
        DataBaseManager.getJdbcTemplate().update("UPDATE calls SET answer_time = CURRENT_TIMESTAMP() WHERE answer_time = 0 and id = ?", callId);
    }

    public List<Call> getCallsHolding() {
        return DataBaseManager.getJdbcTemplate().query("SELECT * FROM calls WHERE answer_time = 0 AND completed_time = 0", mapper);
    }

    public List<Call> getCompletedCalls() {
        return DataBaseManager.getJdbcTemplate().query("SELECT * FROM calls WHERE completed_time != 0 AND answer_time != 0", mapper);
    }

    public Call getLongestHoldingCallByHuntGroup(HuntGroup huntGroup) {
        List<Call> calls = DataBaseManager.getJdbcTemplate().query("SELECT * FROM calls WHERE hunt_group_id = ? AND answer_time = 0 and completed_time = 0", mapper, huntGroup.getId());
        if (!calls.isEmpty()) {
            return calls.get(0);
        } else {
            return null;
        }
    }

    public Call getLatestCompletedCallByUser(User user) {
        List<Call> calls = DataBaseManager.getJdbcTemplate().query("SELECT * FROM calls WHERE answerer_id = ? ORDER BY completed_time DESC", mapper, user.getId());
        if (!calls.isEmpty()) {
            return calls.get(0);
        }
        return null;
    }

    public List<Call> getCompletedCallsByUser(User user) {
        return DataBaseManager.getJdbcTemplate().query("SELECT * FROM calls WHERE answerer_id = ? AND completed_time != 0", mapper, user.getId());
    }

    public List<Call> getAllCalls() {
        return DataBaseManager.getJdbcTemplate().query("SELECT * FROM calls", mapper);
    }
}
